package com.hst.capacity.domain.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.smartravel.traffic.usoft17.RideSupplierCallback;
import cn.smartravel.traffic.usoft17.model.request.callback.OrderStatusDTO;
import cn.smartravel.traffic.usoft17.model.response.callback.ResultVO;
import com.alibaba.fastjson2.JSON;
import com.hst.capacity.domain.common.constants.Constants;
import com.hst.capacity.domain.common.constants.TongChengConstants;
import com.hst.capacity.domain.exception.BusinessException;
import com.hst.capacity.domain.model.entity.order.dispatch.ExpatriateDriverRecordEntity;
import com.hst.capacity.domain.model.entity.order.express.ExpressOrderEntity;
import com.hst.capacity.domain.model.entity.order.express.ExpressOrderStatusHistoryEntity;
import com.hst.capacity.domain.model.entity.order.intercity.IntercityOrderEntity;
import com.hst.capacity.domain.model.entity.order.job.JobPlatformEntity;
import com.hst.capacity.domain.model.request.OrderParam;
import com.hst.capacity.domain.model.request.dispatch.DispatchPartyDriverParam;
import com.hst.capacity.domain.model.request.express.ExListParam;
import com.hst.capacity.domain.model.response.PagingResultVO;
import com.hst.capacity.domain.model.response.driver.DriverInfoVO;
import com.hst.capacity.domain.model.response.order.OrderVO;
import com.hst.capacity.domain.repository.redis.CacheRedis;
import com.hst.capacity.domain.service.AuthService;
import com.hst.capacity.domain.service.DriverService;
import com.hst.capacity.domain.service.ExpressService;
import com.hst.capacity.domain.service.JobPlatformService;
import com.hst.capacity.infra.convertor.DriverConvertor;
import com.hst.capacity.infra.convertor.ExpressConvertor;
import com.hst.capacity.infra.convertor.IntercityConvertor;
import com.hst.capacity.infra.persistence.jpa.order.dispatch.ExpatriateDriverRecordRepoitory;
import com.hst.capacity.infra.persistence.jpa.order.express.ExOrderRepository;
import com.hst.capacity.infra.persistence.jpa.order.express.ExOrderStatusHistoryRepository;
import com.hst.capacity.infra.util.DateUtil;
import com.hst.capacity.infra.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class ExpressServiceImpl implements ExpressService {

    @Autowired
    ExOrderRepository repository;

    @Autowired
    DriverService driverService;

    @Autowired
    JobPlatformService jobPlatformService;

    @Autowired
    ExOrderStatusHistoryRepository orderStatusHistoryRepository;

    @Autowired
    AuthService authService;

    @Autowired
    RideSupplierCallback callback;

    @Autowired
    ExpatriateDriverRecordRepoitory expatriateDriverRecordRepoitory;

    @Autowired
    CacheRedis cacheRedis;

    /**
     * 分页并条件查询今日快车录单信息
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<ExpressOrderEntity> searchWithConditionsAndPaging(ExListParam param) {
        Page<ExpressOrderEntity> page = repository.findAll(new Specification<ExpressOrderEntity>() {
            @Override
            public Predicate toPredicate(Root<ExpressOrderEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                // 定义条件LIST
                List<Predicate> predicates = new ArrayList<Predicate>();
                //idFranchisee
                if (ObjectUtil.isNotEmpty(param.getIdFranchisee())) {
                    predicates.add(criteriaBuilder.equal(root.get("idFranchisee"),param.getIdFranchisee()));
                }
                //status
                if (StrUtil.isNotEmpty(param.getOrderStatus())) {
                    List<Integer> strings = Convert.toList(Integer.class, param.getOrderStatus());
                    CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get("status"));
                    for (Integer v:strings) {
                        in.value(v);
                    }
                    predicates.add(criteriaBuilder.and(in));
                }
                //orderSource
                if (StrUtil.isNotEmpty(param.getOrderSources())) {
                    List<Integer> strings = Convert.toList(Integer.class, param.getOrderSources());
                    CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get("orderSource"));
                    for (Integer v:strings) {
                        in.value(v);
                    }
                    predicates.add(criteriaBuilder.and(in));
                }
                //paymentStatus
                if (StrUtil.isNotEmpty(param.getPayStatus())) {
                    List<Integer> strings = Convert.toList(Integer.class, param.getPayStatus());
                    CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get("paymentStatus"));
                    for (Integer v:strings) {
                        in.value(v);
                    }
                    predicates.add(criteriaBuilder.and(in));
                }
                //regionCode
                if (StrUtil.isNotEmpty(param.getRegionCodes())) {
                    List<Integer> strings = Convert.toList(Integer.class, param.getRegionCodes());
                    CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get("regionCode"));
                    for (Integer v:strings) {
                        in.value(v);
                    }
                    predicates.add(criteriaBuilder.and(in));
                }
                //idOrder
                if (ObjectUtil.isNotEmpty(param.getIdOrder())) {
                    predicates.add(criteriaBuilder.equal(root.get("idOrder"),param.getIdOrder()));
                }
                //orderType
                if (ObjectUtil.isNotEmpty(param.getOrderServiceType())) {
                    predicates.add(criteriaBuilder.equal(root.get("idServiceType"),param.getOrderType()));
                }
                //orderServiceType
                if (ObjectUtil.isNotEmpty(param.getOrderServiceType())) {
                    predicates.add(criteriaBuilder.equal(root.get("inStation"),param.getOrderServiceType()));
                }
                //orderServiceType
                if (ObjectUtil.isNotEmpty(param.getOrderServiceType())) {
                    predicates.add(criteriaBuilder.equal(root.get("inStation"),param.getOrderServiceType()));
                }
                //idStation
                if (ObjectUtil.isNotEmpty(param.getIdStation())) {
                    predicates.add(criteriaBuilder.equal(root.get("idStation"),param.getIdStation()));
                }
                //driverName
//                if (ObjectUtil.isNotEmpty(param.getDriverName())) {
//                    predicates.add(criteriaBuilder.equal(root.get(""),param.getDriverName()));
//                }
                //driverMobile
//                if (ObjectUtil.isNotEmpty(param.getDriverMobile())) {
//                    predicates.add(criteriaBuilder.equal(root.get(""),param.getDriverMobile()));
//                }
                //idAgent
//                if (ObjectUtil.isNotEmpty(param.getIdAgent())) {
//                    predicates.add(criteriaBuilder.equal(root.get(""),param.getIdAgent()));
//                }
                //passengerMobile
                if (ObjectUtil.isNotEmpty(param.getPassengerMobile())) {
                    predicates.add(criteriaBuilder.equal(root.get("passengerMobile"),param.getPassengerMobile()));
                }
                //plateNumber
                if (ObjectUtil.isNotEmpty(param.getPlateNumber())) {
                    predicates.add(criteriaBuilder.equal(root.get("plateNumber"),param.getPlateNumber()));
                }
                //creatTimeF;
                if (ObjectUtil.isNotEmpty(param.getCreatTimeF())) {
                    predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), DateUtil.parseLocalDateTime(param.getCreatTimeF())));
                }
                //creatTimeE
                if (ObjectUtil.isNotEmpty(param.getCreatTimeE())) {
                    predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime"), DateUtil.parseLocalDateTime(param.getCreatTimeE())));
                }

                //排序
                query.orderBy(criteriaBuilder.desc(root.get("createTime")));
                Predicate[] array = predicates.toArray(new Predicate[0]);
                return criteriaBuilder.and(array);
            }
        }, PageRequest.of(param.getPageIndex() - 1, param.getPageSize()));
        return new PagingResultVO(page.getTotalElements(),page.getContent());
    }

    @Override
    public OrderVO virtualAcceptOrder(String idOrder, String idDriver) {
        ExpressOrderEntity order = repository.findByIdOrder(idOrder);
        if (order.getStatus() > Constants.OrderStatus.ORDER_STATUS_ACCEPTED)
            throw new BusinessException(5002,"订单已开始服务，无法虚拟接单。");

        if (order.getStatus() == Constants.OrderStatus.ORDER_STATUS_ACCEPTED &&
                StringUtil.isNotBlank(order.getIdDriver())) {
            if (order.getVirtualOrderAccepted() == 1) {
                return ExpressConvertor.INSTANCE.convert2VO(order);
            } else {
                throw new BusinessException(5002, "订单已安排司机，如需更换司机请执行改派才做。");
            }
        }

        order.setIdDriver(idDriver);
        order.setVirtualOrderAccepted(1);
        if (order.getStatus() < Constants.OrderStatus.ORDER_STATUS_ACCEPTED)
            order.setStatus(Constants.OrderStatus.ORDER_STATUS_ACCEPTED);
        order = repository.save(order);

        log.info("virtualAcceptOrder order" + JSON.toJSONString(order));

        //追加订单状态
        ExpressOrderStatusHistoryEntity orderStatus = new ExpressOrderStatusHistoryEntity();
        orderStatus.setIdOrder(order.getIdOrder());
        orderStatus.setStatus(order.getStatus());
        orderStatus.setCreateBy("capacity");
        orderStatus.setMemo("虚拟接单，虚拟接单司机ID" + idDriver);
        orderStatus = orderStatusHistoryRepository.save(orderStatus);

        log.info("virtualAcceptOrder orderStatus" + JSON.toJSONString(orderStatus));

        return ExpressConvertor.INSTANCE.convert2VO(order);
    }

    @Override
    public int acceptOrder(OrderParam param) {

        ExpressOrderEntity order = repository.findByIdOrder(param.getIdOrder());
        if (order.getStatus() < Constants.OrderStatus.ORDER_STATUS_GOTO_RESERVATION) {
            //实时订单需要做check，并加入idTask
            //派订单给任务
            String idTask = null;
            if (Constants.OrderType.REALTIME == order.getOrderType()) {
                JobPlatformEntity task = jobPlatformService.assignOrderToJob(order, param);
                idTask = task.getIdTask();
            }
            //司机和车辆信息
            DriverInfoVO vo = driverService.driverInfo(param.getIdDriver());
            return repository.driverGrabOrder(param.getIdOrder(), param.getIdDriver(), idTask, Constants.OrderStatus.ORDER_STATUS_ACCEPTED, vo.getPlateNumber(), vo.getVehicleName(), Constants.Def_CreateBy);
        }

        return 0;
    }

    @Override
    public boolean dispatchPartyDriver(DispatchPartyDriverParam param) {

        ExpressOrderEntity order = repository.findByIdOrder(param.getIdOrder());
        if (order == null)
            throw new BusinessException(5002, "订单不存在，请检查参数idOrder是否正确");

        if (order.getOrderSource() == Constants.OrderSource.TONGCHENG_RIDE) {
            OrderStatusDTO dto = new OrderStatusDTO()
                    .setStatus(TongChengConstants.ELong_OrderType.get(Constants.OrderStatus.ORDER_STATUS_ACCEPTED))
                    .setDriverName(param.getDriverName())
                    .setDriverPhone(param.getMobile())
                    .setVehiclePlateNum(param.getPlateNumber())
                    .setVehicleColor(param.getColor())
                    .setVehicleModel(param.getModel())
                    .setVehicleBrand(param.getBrand());

            dto.setOrderId(order.getExternalOrderId());
            dto.setSupplierOrderId(order.getIdOrder());

            String idChannel = authService.findIdChannel(null, order.getIdFranchisee());
            if (StringUtil.isBlank(idChannel))
                throw new BusinessException(5002, "未找到对应的同程渠道，请检查渠道ID");

            ResultVO resultVO = callback.orderStatus(idChannel, dto);
            if (resultVO.getStatus() != 200)
                throw new BusinessException(5002, "同程接口回调失败，请重新执行");
        }

        //加盟商指定自有司机账户
        order.setIdDriver(order.getIdDriver());
        order.setDriverInfo(param.getDriverName()+"/"+param.getMobile());
        order.setVirtualOrderAccepted(0);
        order.setStatus(Constants.OrderStatus.ORDER_STATUS_ACCEPTED);
        order.setDriverMemo("电话："+ param.getMobile() + ",车牌号：" + param.getPlateNumber());
        repository.save(order);

        //外调记录
        ExpatriateDriverRecordEntity recordEntity = expatriateDriverRecordRepoitory.findByIdOrderAndDriverMobile(param.getIdOrder(),param.getMobile());
        if (recordEntity == null)
            recordEntity = new ExpatriateDriverRecordEntity();

        recordEntity.setIdOrder(param.getIdOrder());
        recordEntity.setDriverMobile(param.getMobile());
        recordEntity.setDriverName(param.getDriverName());
        recordEntity.setPlateNumber(param.getPlateNumber());
        recordEntity.setBrand(param.getBrand());
        recordEntity.setColor(param.getColor());
        recordEntity.setModel(param.getModel());
        if (StringUtil.isNotBlank(order.getExternalOrderId()))
            recordEntity.setExternalOrderId(order.getExternalOrderId());
        recordEntity.setMemo("外派渠道"+order.getOrderSource());
        expatriateDriverRecordRepoitory.save(recordEntity);

        //外调记录
        if (StringUtil.isNotBlank(order.getExternalOrderId())) {
            DriverInfoVO driverInfoVO = DriverConvertor.INSTANCE.convert2Info(param);
            cacheRedis.writePartyDriverValue(order.getIdOrder(), JSON.toJSONString(driverInfoVO));
        }

        return true;
    }

    @Override
    public OrderVO findOrderByIdOrder(String idOrder) {
        ExpressOrderEntity order = repository.findByIdOrder(idOrder);
        if (order == null)
            throw new BusinessException(5002, "订单不存在，请检查参数idOrder是否正确");

        return ExpressConvertor.INSTANCE.convert2VO(order);
    }

//    /**
//     * 订单操作履历
//     * @param param
//     * @return
//     */
//    @Override
//    public ExpressOrderOperationHistory createOrderOperationHistory(ExOperationHistoryParam param){
//
//    }

//    public PagingResultVO<ExpressOrderEntity> searchWithConditionsAndPaging(DriverSearchParam param) {
//        Page<ExpressOrderEntity> page = repository.findAll(new Specification<ExpressOrderEntity>() {
//
//            @Override
//            public Predicate toPredicate(Root<ExpressOrderEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
//                return null;
//            }
//        }, PageRequest.of(param.getPageIndex() - 1, param.getPageSize()));
//        return new PagingResultVO(page.getTotalPages(),page.getContent());
//    }
}
